#include <QgsSimulation/MapCanvas.h>
#include <qgsproject.h>
#include <qgsapplication.h>
using SimulationCore::QgsSimulation::MapCanvas;

MapCanvas::MapCanvas(QWidget* parent) 
: QgsMapCanvas(parent)
, m_minScale(0.1)
, m_maxScale(100000.0)
{
	connect(this, &QgsMapCanvas::scaleChanged, this, &MapCanvas::onScaleChange);
}

void MapCanvas::UseGPU(bool use)
{
	if (use)
	{
		this->setViewport(new QOpenGLWidget());
	}
	else
	{
		this->setViewport(new QWidget());
	}
}

void MapCanvas::SetScaleRange(double min, double max)
{
	m_minScale = min;
	m_maxScale = max;
}

void MapCanvas::GetScale(double &min, double &max)
{
	min = m_minScale;
	max = m_maxScale;
}

void MapCanvas::dragEnterEvent(QDragEnterEvent * event)
{
	event->acceptProposedAction();
	/*if (event->mimeData()->hasText()) {
		event->acceptProposedAction();
	}*/
	// qDebug() << "dragEnterEvent" << endl;
}


void MapCanvas::dropEvent(QDropEvent * event)
{
	QPointF scenePos = mapToScene(event->pos());
	const QgsMapToPixel* ct = getCoordinateTransform();
	QgsPointXY mapPos = ct->toMapCoordinates(scenePos.x(), scenePos.y());

	emit dropAddDataEvent(mapPos.x(), mapPos.y(), event->mimeData());
	event->acceptProposedAction();
}

void MapCanvas::wheelEvent(QWheelEvent * e)
{
	QPointF scenePos = mapToScene(e->pos());
	const QgsMapToPixel* ct = getCoordinateTransform();
	QgsPointXY mapPos = ct->toMapCoordinates(scenePos.x(), scenePos.y());

	//qDebug() << << "scale:" << scale()<<std::endl;

	int delta = e->delta();
	if (delta > 0) {
		if(scale() <= m_minScale) {
			// if current scale is already at the minimum, don't zoom in
			return; 
		}
		zoomIn();
	}
	else {
		if(scale() >= m_maxScale) {
			// if current scale is already at the maximum, don't zoom out
			return; 
		}
		zoomOut();
	}

	setCenter(mapPos);
}

void MapCanvas::onMouseMoveShowCoordinates(const QgsPointXY &point)
{
	emit showCoordinates(point.x(), point.y());
}

void MapCanvas::onScaleChange(double currnt_scale)
{
	//qDebug() << currnt_scale;
}

void MapCanvas::mousePressEvent(QMouseEvent * e)
{
	if(e->button() == Qt::MiddleButton)
	{
		return;
	}

	// if left button and Ctrl key is pressed, start panning
	if (e->button() == Qt::LeftButton && QgsApplication::keyboardModifiers() & Qt::ControlModifier) {
		m_lastPanPoint = e->pos();
		m_panActive = true;
		setCursor(Qt::ClosedHandCursor);
		e->accept();
	} else {
		emit clickedCoordinates(
			getCoordinateTransform()->toMapCoordinates(e->pos()).x(),
			getCoordinateTransform()->toMapCoordinates(e->pos()).y()
		);
		QgsMapCanvas::mousePressEvent(e); 
	}
}

void MapCanvas::mouseMoveEvent(QMouseEvent * e)
{
	if(e->button() == Qt::MiddleButton)
	{
		return;
	}

	if (m_panActive) {
		QPoint delta = e->pos() - m_lastPanPoint;
		pan(delta);
		m_lastPanPoint = e->pos();
		e->accept();
	} else {
		
	}

	QgsMapCanvas::mouseMoveEvent(e);
}

void MapCanvas::mouseReleaseEvent(QMouseEvent * e)
{
	if(e->button() == Qt::MiddleButton)
	{
		return;
	}

	if (m_panActive && e->button() == Qt::LeftButton) {
		m_panActive = false;
		unsetCursor();
		e->accept();
	} else {
		QgsMapCanvas::mouseReleaseEvent(e);
	}
}


void MapCanvas::pan(const QPoint& delta) {
        // transform mouse coordinates to map coordinates
        QgsPointXY startPt = getCoordinateTransform()->toMapCoordinates(m_lastPanPoint);
        QgsPointXY endPt = getCoordinateTransform()->toMapCoordinates(m_lastPanPoint - delta);

		double dx = endPt.x() - startPt.x();
    	double dy = endPt.y() - startPt.y();

        QgsRectangle extent = this->extent();
        extent.setXMinimum(extent.xMinimum() + dx);
		extent.setXMaximum(extent.xMaximum() + dx);
		extent.setYMinimum(extent.yMinimum() + dy);
		extent.setYMaximum(extent.yMaximum() + dy);

        setExtent(extent);
        // refresh();
    }
